home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / Perl / macperl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-29  |  30.4 KB  |  1,419 lines

  1. /*********************************************************************
  2. File        :    macperl.c    - Mac specific extensions
  3. Author    :    Matthias Neeracher & Tim Endres
  4. Started    :    28May91                                Language    :    MPW C
  5.                 31Oct93    MN    XCMDs
  6.                 05Dec93    MN    Faccess
  7. Last        :    05Dec93
  8.  
  9. Copyright (c) 1991-93 Matthias Neeracher & Tim Endres
  10. *********************************************************************/
  11.  
  12. #include <Types.h>
  13. #include <Resources.h>
  14. #include <QuickDraw.h>
  15. #include <Fonts.h>
  16. #include <Menus.h>
  17. #include <TextEdit.h>
  18. #include <Dialogs.h>
  19. #include <SegLoad.h>
  20. #include <StandardFile.h>
  21. #include <Lists.h>
  22. #include <Files.h>
  23. #include <Memory.h>
  24. #include <TFileSpec.h>
  25. #include <Components.h>
  26. #include <AppleEvents.h>
  27. #include <OSA.h>
  28. #include <AppleScript.h>
  29. #include <AERegistry.h>
  30. #include <AESubDescs.h>
  31. #include <OSUtils.h>
  32. #include <HyperXCmd.h>
  33. #include <Gestalt.h>
  34. #define XLDEBUG
  35. #include <XL.h>
  36. #include <TextUtils.h>
  37. #include <FCntl.h>
  38.  
  39. /* Ugly hack since QuickDraw defines another invert */
  40. #define RESOLVE_MAC_CONFLICTS
  41.  
  42. #include "EXTERN.h"
  43. #include "perl.h"
  44.  
  45. void InitToolbox()
  46. {
  47.     InitGraf((Ptr) &qd.thePort);
  48. }
  49.  
  50. static int macperlsub();
  51. static int macperlset();
  52. static int macperlval();
  53. static int doapscript();
  54. static int xlsub();
  55. static void loadresfile();
  56. static void PerlXLGetGlobal(XCmdPtr params);
  57. static void PerlXLSetGlobal(XCmdPtr params);
  58.  
  59. enum {
  60.     MP_fsetfileinfo,
  61.     MP_fgetfileinfo,
  62.     MP_ask,
  63.     MP_answer,
  64.     MP_choose,
  65.     MP_pick,
  66.     MP_quit,
  67.     MP_faccess,
  68.     MP_makefsspec,
  69.     MP_makepath,
  70.     MP_volumes,
  71.     
  72.     MP_doapplescript = 0,
  73.     MP_reply,
  74.     
  75.     MP_loadexternals  = 0,
  76.     MP_debugexternals = 1,
  77.     MP_extension        = 2
  78. };
  79.  
  80. enum {
  81.     MV_version
  82. };
  83.  
  84. void ShutdownAppleEvents(void)
  85. {
  86. }
  87.  
  88. Boolean    hasAppleEvents;
  89. Boolean    hasComponents;
  90. XLGlue     XLPerlGlue;
  91.  
  92. int 
  93. macperlinit()
  94. {
  95.     struct ufuncs    uf;
  96.     long                res;
  97.     int                 saveallstabs = allstabs;
  98.     
  99.     allstabs = TRUE;
  100.     gPerlQuit = 0;
  101.     
  102.     make_usub("MacPerl'SetFileInfo", MP_fsetfileinfo,    macperlsub, "macperl.c");
  103.     make_usub("MacPerl'GetFileInfo", MP_fgetfileinfo,    macperlsub, "macperl.c");
  104.     make_usub("MacPerl'Ask",             MP_ask,                macperlsub, "macperl.c");
  105.     make_usub("MacPerl'Answer",         MP_answer,            macperlsub, "macperl.c");
  106.     make_usub("MacPerl'Choose",         MP_choose,            macperlsub, "macperl.c");
  107.     make_usub("MacPerl'Pick",             MP_pick,                macperlsub, "macperl.c");
  108.     make_usub("MacPerl'Quit",             MP_quit,                macperlsub, "macperl.c");
  109.     make_usub("MacPerl'FAccess",         MP_faccess,            macperlsub, "macperl.c");
  110.     make_usub("MacPerl'MakeFSSpec",     MP_makefsspec,        macperlsub, "macperl.c");
  111.     make_usub("MacPerl'MakePath",     MP_makepath,        macperlsub, "macperl.c");
  112.     make_usub("MacPerl'Volumes",         MP_volumes,            macperlsub, "macperl.c");
  113.  
  114.     make_usub("MacPerl'DoAppleScript",    MP_doapplescript, doapscript, "macperl.c");
  115.     make_usub("MacPerl'Reply",            MP_reply,             doapscript, "macperl.c");
  116.     
  117.     make_usub("MacPerl'LoadExternals",     MP_loadexternals, xlsub,         "macperl.c");
  118.     make_usub("MacPerl'DebugExternals", MP_debugexternals, xlsub,         "macperl.c");
  119.     
  120.     uf.uf_set         = macperlset;
  121.     uf.uf_val         = macperlval;
  122.     uf.uf_index    = MV_version;
  123.     magicname("MacPerl'Version", (char *)&uf, sizeof uf);
  124.     
  125.     loadresfile(gAppFile);
  126.     
  127.     if (gPrefsFile)
  128.         loadresfile(gPrefsFile);
  129.     
  130.     if (Gestalt(gestaltAppleEventsAttr, &res))
  131.         hasAppleEvents = false;
  132.     else 
  133.         hasAppleEvents = (res & (1<<gestaltAppleEventsPresent)) != 0;
  134.  
  135.     hasComponents = !Gestalt(gestaltComponentMgr, &res);
  136.     
  137.     allstabs = saveallstabs;
  138.     
  139.     XLCopyGlue(XLPerlGlue, XLDefaultGlue);
  140.     
  141.     XLPerlGlue[xl_GetGlobal]    =    PerlXLGetGlobal;
  142.     XLPerlGlue[xl_SetGlobal]    =    PerlXLSetGlobal;
  143.  
  144.     return 0;
  145. }
  146.  
  147. static void PerlXLGetGlobal(XCmdPtr params)
  148. {
  149.     StringPtr     var    =    (StringPtr) params->inArgs[0];
  150.     char            ch     =     0;
  151.     STAB *        stab;
  152.     STR *            str;
  153.     STRLEN        len;
  154.     
  155.     if (stab = stabent(p2cstr(var), allstabs)) {
  156.         str = stab_val(stab);
  157.         len = str_len(str);
  158.         PtrToHand(str_get(str), (Handle *) ¶ms->outArgs[0], len+1);
  159.         (*(Handle) params->outArgs[0])[len] = 0;
  160.     } else
  161.         PtrToHand(&ch, (Handle *) ¶ms->outArgs[0], 1);
  162.         
  163.     c2pstr((char *) var);
  164.     
  165.     params->result = xresSucc;    
  166. }
  167.  
  168. static void PerlXLSetGlobal(XCmdPtr params)
  169. {
  170.     StringPtr     var    =    (StringPtr) params->inArgs[0];
  171.     Handle        val    =     (Handle) params->inArgs[1];
  172.     char            ch     =     0;
  173.     STAB *        stab;
  174.     STRLEN        len;
  175.     
  176.     HLock(val);
  177.     if (stab = stabent(p2cstr(var), allstabs))
  178.         str_set(stab_val(stab), *val);
  179.     c2pstr((char *) var);
  180.     HUnlock(val);
  181.     
  182.     params->result = xresSucc;    
  183. }
  184.  
  185. typedef struct {
  186.     short        refNum;
  187.     FSSpec    file;
  188. } ResourceFile;
  189.  
  190. typedef struct {
  191.     short                count;
  192.     ResourceFile    file[1];
  193. } ** ResourceFiles;
  194.  
  195. typedef struct {
  196.     short        refNum;
  197.     ResType    type;
  198.     short        id;
  199. } Xternal, ** XternalHdl;
  200.  
  201. static ResourceFiles ResFiles;
  202. static XternalHdl        Xternals;
  203. static int                XternalIndex = 0;
  204. static Boolean            CloseInstalled = false;
  205.  
  206. void CloseResFiles(void)
  207. {
  208.     if (ResFiles) {
  209.         while ((*ResFiles)->count--)
  210.             CloseResFile((*ResFiles)->file[(*ResFiles)->count].refNum);
  211.         
  212.         DisposeHandle((Handle) ResFiles);
  213.         
  214.         ResFiles = nil;
  215.     }
  216.     
  217.     if (Xternals) {
  218.         DisposeHandle((Handle) Xternals);
  219.         
  220.         Xternals = nil;
  221.     }
  222.     
  223.     XternalIndex     =     0;
  224.     CloseInstalled    =    false;
  225. }
  226.  
  227. static ResType SearchTypes[] = {'XCMD', 'XFCN', 0};
  228.  
  229. static void loadresfile(short refNum) 
  230. {
  231.     Handle            xcmd;
  232.     ResType *        type;
  233.     short                count;
  234.     short                id;
  235.     ResType            rtyp;
  236.     short                oldRes = CurResFile();
  237.     Xternal            x;
  238.     char                name[256];
  239.    int saveallstabs = allstabs;
  240.     allstabs = TRUE;
  241.     
  242.     if (!CloseInstalled) {
  243.         atexit(CloseResFiles);
  244.         CloseInstalled = true;
  245.     }
  246.         
  247.     if (!Xternals)
  248.         Xternals = (XternalHdl) NewHandle(0);
  249.     
  250.     UseResFile(refNum);
  251.     
  252.     for (type = SearchTypes; *type; ++type)
  253.         for (count = Count1Resources(*type); count; --count)
  254.             if (xcmd = Get1IndResource(*type, count)) {
  255.                 getresinfo(xcmd, &id, &rtyp, name);
  256.                 
  257.                 x.refNum = refNum;
  258.                 x.type    = rtyp;
  259.                 x.id        = id;
  260.                 
  261.                 PtrAndHand((Ptr) &x, (Handle) Xternals, sizeof(Xternal));
  262.                 
  263.                 make_usub(name, MP_extension + XternalIndex++, xlsub, "macperl.c");
  264.             }
  265.             
  266.     UseResFile(oldRes);
  267.     allstabs = saveallstabs;
  268. }
  269.  
  270. OSErr tryresload(FSSpec * spec)
  271. {
  272.     short                i;
  273.     short                refNum;
  274.     ResourceFile    file;
  275.     
  276.     if (!ResFiles) {
  277.         i = 0;
  278.         
  279.         PtrToHand((Ptr) &i, (Handle *) &ResFiles, sizeof(short));
  280.     }
  281.     
  282.     for (i = (*ResFiles)->count; i--; ) {
  283.         ResourceFile * file = (*ResFiles)->file + i;
  284.         
  285.         if (file->file.vRefNum != spec->vRefNum)
  286.             continue;
  287.         if (file->file.parID != spec->parID)
  288.             continue;
  289.             
  290.         if (EqualString(file->file.name, spec->name, false, true))
  291.             return 0;
  292.     }
  293.     
  294.     refNum = HOpenResFile(spec->vRefNum, spec->parID, spec->name, fsRdPerm);
  295.     
  296.     if (refNum == -1)
  297.         return ResError();
  298.     
  299.     file.refNum = refNum;
  300.     file.file     = *spec;
  301.     
  302.     PtrAndHand((Ptr) &file, (Handle) ResFiles, sizeof(ResourceFile));
  303.     ++(*ResFiles)->count;
  304.     
  305.     loadresfile(refNum);
  306.     
  307.     return 0;
  308. }
  309.  
  310. OSErr loadresinclude(char * path)
  311. {
  312.     int        i;
  313.    ARRAY *    ar;
  314.     char        buf[256];
  315.     FSSpec    spec;
  316.     
  317.     if (strchr(path, ':'))
  318.         if (!Path2FSSpec(path, &spec))
  319.             return tryresload(&spec);
  320.         else
  321.             return 1;
  322.         
  323.     ar = stab_array(incstab);
  324.     for (i = 0; i <= ar->ary_fill; i++) {
  325.         char *macptr = str_get(afetch(ar,i,TRUE));
  326.         int   colon = macptr[strlen(macptr)-1] == ':';
  327.         
  328.         if (colon)
  329.             (void) sprintf(buf, "%s%s", macptr, path);
  330.         else 
  331.             (void) sprintf(buf, "%s:%s", macptr, path);
  332.     
  333.         if (!Path2FSSpec(buf, &spec) && !tryresload(&spec))
  334.             return 0;
  335.     }
  336.     
  337.     return 1;
  338. }
  339.  
  340. static void xlsetupparams(STR ** st, int items, XCmdPtr xcmd)
  341. {
  342.     int i;
  343.     STR *Str;        /* used in str_get and str_gnum macros */
  344.  
  345.     xcmd->paramCount = items;
  346.     for (i = 0; i < items; ++i) {
  347.         char * arg = str_get(st[i+1]);
  348.         
  349.         PtrToHand(arg, xcmd->params+i, strlen(arg)+1);
  350.     }
  351.     
  352.     for (i = items; i < 16; ++i)
  353.         xcmd->params[i] = nil;
  354.     
  355.     xcmd->returnValue = nil;
  356.     xcmd->passFlag      = 0;
  357. }
  358.  
  359. static void xldisposeparams(STR ** st, int items, XCmdPtr xcmd)
  360. {
  361.     int i;
  362.     
  363.     for (i=0; i<16; ++i)
  364.         if (xcmd->params[i])
  365.             DisposeHandle(xcmd->params[i]);
  366.     
  367.     if (xcmd->returnValue) {
  368.         HLock(xcmd->returnValue);
  369.         st[0] = str_2mortal(str_make(*xcmd->returnValue, 0));        
  370.         DisposeHandle(xcmd->returnValue);
  371.     } else
  372.         st[0] = &str_undef;
  373. }    
  374.  
  375. static int 
  376. xlcall(ix, sp, items)
  377. int ix;
  378. int sp;
  379. int items;
  380. {
  381.     STR **st = stack->ary_array + sp;
  382.     short                    resFile;
  383.     struct XCmdBlock    xcmd;
  384.     Xternal                xt;
  385.     Handle                xh;
  386.     
  387.     xlsetupparams(st, items, &xcmd);
  388.     
  389.     xt = (*Xternals)[ix-MP_extension];
  390.     
  391.     resFile = CurResFile();
  392.     UseResFile(xt.refNum);
  393.     
  394.     xh = Get1Resource(xt.type, xt.id);
  395.     
  396.     if (!xh)
  397.         fatal("XCMD disppeared. Film at 11!");
  398.         
  399.     XLCall(xh, XLPerlGlue, &xcmd);
  400.  
  401.     UseResFile(resFile);
  402.  
  403.     xldisposeparams(st, items, &xcmd);
  404.     
  405.     return sp;
  406. }
  407.  
  408. static int
  409. xlsub(ix, sp, items)
  410. int ix;
  411. int sp;
  412. int items;
  413. {
  414.     STR **st = stack->ary_array + sp;
  415.     STR *Str;        /* used in str_get and str_gnum macros */
  416.  
  417.     switch (ix) {
  418.     case MP_loadexternals:
  419.         if (items != 1)
  420.             fatal("Usage: $MacPerl'LoadExternals(LIB)");
  421.  
  422.          switch (loadresinclude(str_get(st[1]))) {
  423.         case 0:
  424.             break;
  425.         case 1:
  426.             fatal("MacPerl'LoadExternals(\"%s\"): File not found.\n", str_get(st[1]));
  427.         default:
  428.             fatal("MacPerl'LoadExternals(\"%s\"): Error opening file.\n", str_get(st[1]));
  429.         }
  430.         
  431.         st[0] = &str_undef;
  432.  
  433.         return sp;
  434.     case MP_debugexternals:
  435.         if (items != 1)
  436.             fatal("Usage: $MacPerl'DebugExternals(LEVEL)");
  437.  
  438.         str_numset(st[0], (double) XLDebug);
  439.  
  440.         XLDebug = (XLDebugLevel) str_gnum(st[1]);
  441.         
  442.         return sp;        
  443.     default:
  444.         return xlcall(ix, sp, items);
  445.     }
  446. }
  447.  
  448. static void CenterWindow(DialogPtr dlg)
  449. {
  450.     Rect    *        screen;
  451.     short            hPos;
  452.     short            vPos;
  453.     
  454.     screen    =    &qd.screenBits.bounds;
  455.     hPos    =    screen->right+screen->left-dlg->portRect.right >> 1;
  456.     vPos    =    (screen->bottom-screen->top-dlg->portRect.bottom)/3;
  457.     vPos    +=    screen->top;
  458.     MoveWindow(dlg, hPos, vPos, true);
  459. }    
  460.  
  461. static ControlHandle GetDlgCtrl(DialogPtr dlg, short item)
  462. {
  463.     short     kind;
  464.     Handle    hdl;
  465.     Rect    box;
  466.     
  467.     GetDItem(dlg, item, &kind, &hdl, &box);
  468.     return (ControlHandle) hdl;
  469. }
  470.  
  471. static void GetDlgText(DialogPtr dlg, short item, char * text)
  472. {
  473.     getitext((Handle) GetDlgCtrl(dlg, item), text);
  474. }
  475.  
  476. static void SetDlgText(DialogPtr dlg, short item, char * text)
  477. {
  478.     setitext((Handle) GetDlgCtrl(dlg, item), text);
  479. }
  480.  
  481. static void GetDlgRect(DialogPtr dlg, short item, Rect * r)
  482. {
  483.     short     kind;
  484.     Handle    hdl;
  485.     
  486.     GetDItem(dlg, item, &kind, &hdl, r);
  487. }
  488.  
  489. static void FrameDlgRect(DialogPtr dlg, short item)
  490. {
  491.     Rect    r;
  492.     
  493.     GetDlgRect(dlg, item, &r);
  494.     InsetRect(&r, -4, -4);
  495.     PenSize(3, 3);
  496.     FrameRoundRect(&r, 16, 16);
  497.     PenSize(1,1);
  498. }
  499.  
  500. #define TempPStr(cstr)    ((StringPtr) memcpy(tmpPStr+1, cstr, *tmpPStr = strlen(cstr)), tmpPStr)
  501.  
  502. double
  503. do_answer(arglast)
  504.     int *arglast;
  505. {
  506.     register STR **st = stack->ary_array;
  507.     register int sp = arglast[0];
  508.     int            maxarg = arglast[2] - sp;
  509.     char *        prompt;
  510.     short        item;
  511.     DialogPtr    dlg;
  512.     Str255        tmpPStr;
  513.  
  514.     if (maxarg > 4)
  515.         fatal("answer() called with more than 4 arguments");
  516.         
  517.     prompt = (char*)str_get(st[++sp]);
  518.  
  519.     dlg = GetNewDialog((maxarg>1) ? 1999+maxarg : 2001, NULL, (WindowPtr)-1);
  520.     InitCursor();
  521.     SetDlgText(dlg, 5, prompt);
  522.     
  523.     if (maxarg>1) 
  524.         for (item = 1; item<maxarg; ++item) {
  525.             prompt = (char*)str_get(st[++sp]);
  526.             memcpy(tmpPStr+1, prompt, *tmpPStr = st[sp]->str_cur);
  527.             SetCTitle(GetDlgCtrl(dlg, item), tmpPStr);
  528.         }
  529.     else
  530.         SetCTitle(GetDlgCtrl(dlg, 1), (StringPtr) "\pOK");
  531.     
  532.     CenterWindow(dlg);
  533.     ShowWindow(dlg);
  534.     SetPort(dlg);
  535.     FrameDlgRect(dlg, ok);
  536.     ModalDialog((ModalFilterUPP)0, &item);
  537.     DisposDialog(dlg);
  538.     
  539.     return (maxarg>1) ? maxarg-item-1 : 0;
  540. }
  541.  
  542. static char     string_reply[256];
  543.  
  544. STR * do_ask(arglast, maxarg)
  545.     int *arglast;
  546.     int maxarg;
  547. {
  548.     register STR **st = stack->ary_array;
  549.     register int sp = arglast[0];
  550.     char *        prompt;
  551.     short        item;
  552.     DialogPtr    dlg;
  553.     STR *         str;
  554.  
  555.     if (maxarg > 2)
  556.         fatal("ask() called with more than 2 arguments");
  557.         
  558.     prompt = (char*)str_get(st[++sp]);
  559.  
  560.     dlg = GetNewDialog(2010, NULL, (WindowPtr)-1);
  561.     InitCursor();
  562.     SetDlgText(dlg, 3, prompt);
  563.     
  564.     if (maxarg == 2)
  565.         SetDlgText(dlg, 4, (char*)str_get(st[++sp]));
  566.     SelIText(dlg, 4, 0, 1024);
  567.  
  568.     InitCursor();
  569.     CenterWindow(dlg);
  570.     ShowWindow(dlg);
  571.     SetPort(dlg);
  572.     FrameDlgRect(dlg, ok);
  573.     ModalDialog((ModalFilterUPP)0, &item);
  574.     switch (item) {
  575.     case ok:
  576.         str = str_2mortal(Str_new(22,257));
  577.         str->str_cur = 256;
  578.            str->str_pok = 1;
  579.         GetDlgText(dlg, 4, str->str_ptr);
  580.         str->str_cur = strlen(str->str_ptr);
  581.         break;
  582.     case cancel:
  583.         break;
  584.     }
  585.     DisposDialog(dlg);
  586.     
  587.     return (item == ok) ? str : &str_undef;
  588. }
  589.  
  590. static ListHandle picklist = NULL;
  591.  
  592. #define SetCell(cell, row, column)    { (cell).h = column; (cell).v = row; }
  593. #define ROW(cell)                     (cell).v
  594.  
  595. pascal void
  596. MacListUpdate(myDialog, myItem)
  597. DialogPtr        myDialog;
  598. short            myItem;
  599. {
  600.     Rect            myrect;
  601.  
  602.     LUpdate(myDialog->visRgn, picklist);
  603.     myrect = (**(picklist)).rView;
  604.     InsetRect(&myrect, -1, -1);
  605.     FrameRect(&myrect);
  606. }
  607.  
  608. #if USESROUTINEDESCRIPTORS
  609. RoutineDescriptor    uMacListUpdate = 
  610.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, MacListUpdate);
  611. #else
  612. #define uMacListUpdate MacListUpdate
  613. #endif
  614.  
  615. pascal Boolean
  616. MacListFilter(myDialog, myEvent, myItem)
  617. DialogPtr        myDialog;
  618. EventRecord        *myEvent;
  619. short            *myItem;
  620. {
  621.     Rect    listrect;
  622.     short    myascii;
  623.     Handle    myhandle;
  624.     Point    mypoint;
  625.     short    mytype;
  626.     int        activate;
  627.  
  628.     SetPort(myDialog);
  629.     if (myEvent->what == keyDown) {
  630.         myascii = myEvent->message % 256;
  631.         if (myascii == '\015' || myascii == '\003') {    /* This is return or enter... */
  632.             *myItem = 1;
  633.             return true;
  634.             }
  635.         }
  636.     else if (myEvent->what == mouseDown) {
  637.         mypoint = myEvent->where;
  638.         GlobalToLocal(&mypoint);
  639.         GetDItem(myDialog, 4, &mytype, &myhandle, &listrect);
  640.         if (PtInRect(mypoint, &listrect) && picklist != NULL) {
  641.             if (LClick(mypoint, (short)myEvent->modifiers, picklist)) {
  642.                 /* User double-clicked in cell... */
  643.                 *myItem = 1;
  644.                 return true;
  645.                 }
  646.             }
  647.         }
  648.     else if (myEvent->what == activateEvt && picklist != NULL) {
  649.         activate = (myEvent->modifiers & 0x01) != 0;
  650.         LActivate((Boolean) activate, picklist);
  651.         }
  652.     
  653.     return false;
  654. }
  655.  
  656. #if USESROUTINEDESCRIPTORS
  657. RoutineDescriptor    uMacListFilter = 
  658.         BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, MacListFilter);
  659. #else
  660. #define uMacListFilter MacListFilter
  661. #endif
  662.  
  663. STR *
  664. do_pick(arglast)
  665.     int *arglast;
  666. {
  667.     register STR **st = stack->ary_array;
  668.     register int sp = arglast[0];
  669.     int            maxarg = arglast[2] - sp - 1;
  670.     char *        prompt;
  671.     short        itemHit;
  672.     Boolean        done;
  673.     DialogPtr    dlg;
  674.     ListHandle    mylist;
  675.     Cell        mycell;
  676.     short        mytype;
  677.     Handle        myhandle;
  678.     Point        cellsize;
  679.     Rect        listrect, dbounds;
  680.     char    *    item;
  681.  
  682.     prompt = (char*)str_get(st[++sp]);
  683.     InitCursor();
  684.     dlg = GetNewDialog(2020, NULL, (WindowPtr)-1);
  685.     
  686.     SetDlgText(dlg, 3, prompt);
  687.     GetDItem(dlg, 4, &mytype, &myhandle, &listrect);
  688.     SetDItem(dlg, 4, mytype, (Handle)&uMacListUpdate, &listrect);
  689.     
  690.     SetPort(dlg);
  691.     InsetRect(&listrect, 1, 1);
  692.     SetRect(&dbounds, 0, 0, 1, maxarg);
  693.     cellsize.h = (listrect.right - listrect.left);
  694.     cellsize.v = 17;
  695.  
  696.     listrect.right -= 15;
  697.  
  698.     picklist = LNew(&listrect, &dbounds, cellsize, 0,
  699.                             dlg, true, false, false, true);
  700.  
  701.     mylist = picklist;
  702.     LDoDraw(false, mylist);
  703.     
  704.     SetCell(mycell, 0, 0);
  705.     for (; mycell.v<maxarg; ++mycell.v)    {
  706.         item = str_get(st[++sp]);
  707.         LSetCell(item, st[sp]->str_cur, mycell, mylist);
  708.     }
  709.  
  710.     LDoDraw(true, mylist);
  711.     CenterWindow(dlg);
  712.     ShowWindow(dlg);
  713.     
  714.     for (done=false; !done; ) {
  715.         SetPort(dlg);
  716.         FrameDlgRect(dlg, ok);
  717.         ModalDialog((ModalFilterUPP) &uMacListFilter, &itemHit);
  718.         switch (itemHit) {
  719.         case ok:
  720.             SetCell(mycell, 0, 0);
  721.             done = true;
  722.             if (!LGetSelect(true, &mycell, picklist))
  723.                 itemHit = cancel;
  724.             break;
  725.         case cancel:
  726.             done = true;
  727.             break;
  728.         }
  729.     }    /* Modal Loop */
  730.  
  731.     SetPort(dlg);
  732.     
  733.     LDispose(mylist);
  734.     picklist = NULL;
  735.     DisposDialog(dlg);
  736.     
  737.     if (itemHit == ok)
  738.         return str_smake(st[arglast[0]+mycell.v+2]);
  739.     else
  740.         return &str_undef;    
  741. }
  742.  
  743. static OSErr GetVolInfo(short volume, Boolean indexed, FSSpec * spec)
  744. {
  745.     OSErr                err;
  746.     HParamBlockRec    pb;
  747.     
  748.     pb.volumeParam.ioNamePtr    =    spec->name;
  749.     pb.volumeParam.ioVRefNum    =    indexed ? 0 : volume;
  750.     pb.volumeParam.ioVolIndex    =    indexed ? volume : 0;
  751.     
  752.     if (err = PBHGetVInfoSync(&pb))
  753.         return err;
  754.     
  755.     spec->vRefNum    =    pb.volumeParam.ioVRefNum;
  756.     spec->parID        =    1;
  757.     
  758.     return noErr;
  759. }
  760.  
  761. static int
  762. macperlsub(ix, sp, items)
  763. int ix;
  764. register int sp;
  765. register int items;
  766. {
  767.     STR **st = stack->ary_array + sp;
  768.     register int i;
  769.     register STR *Str;        /* used in str_get and str_gnum macros */
  770.      
  771.      switch (ix) {
  772.      case MP_fsetfileinfo:
  773.          {
  774.             unsigned long    creator;
  775.             unsigned long    type;
  776.             
  777.             if (items < 3)
  778.                 fatal("Usage: &MacPerl'SetFileInfo(CREATOR, TYPE, FILE...)");
  779.                 
  780.              creator    = *(unsigned long*)    str_get(st[1]);
  781.              type        = *(unsigned long*)    str_get(st[2]);
  782.             
  783.              for (i = 3; i<=items; i++)
  784.                  fsetfileinfo(str_get(st[i]), creator, type);
  785.                     
  786.              st[0] = &str_undef;
  787.      
  788.              return sp;
  789.         }
  790.     case MP_fgetfileinfo:
  791.         {
  792.              unsigned long    creator;
  793.              unsigned long    type;
  794.  
  795.             if (items != 1)
  796.                 fatal("Usage: &MacPerl'GetFileInfo(PATH)");
  797.  
  798.             fgetfileinfo(str_get(st[1]), &creator, &type);
  799.             
  800.             if (errno) {
  801.                  st[0] = &str_undef;
  802.      
  803.                  return sp;
  804.             }
  805.                 
  806.             if (!curcsv || curcsv->wantarray != G_ARRAY) {
  807.                 str_nset(st[0], &type, 4);
  808.                 return sp;
  809.             }
  810.             st[0] = str_2mortal(str_make(&creator,4));
  811.             st[1] = str_2mortal(str_make(&type,4));
  812.             return sp + 1;
  813.         }
  814.     case MP_ask:
  815.         {
  816.             char *        prompt;
  817.             short            item;
  818.             DialogPtr    dlg;
  819.             STR *         str;
  820.         
  821.             if (items < 1 || items > 2)
  822.                 fatal("Usage: &MacPerl'Ask(PROMPT [, DEFAULT])");
  823.                 
  824.             prompt = (char*)str_get(st[1]);
  825.         
  826.             dlg = GetNewDialog(2010, NULL, (WindowPtr)-1);
  827.             InitCursor();
  828.             SetDlgText(dlg, 3, prompt);
  829.             
  830.             if (items == 2)
  831.                 SetDlgText(dlg, 4, (char*)str_get(st[2]));
  832.             SelIText(dlg, 4, 0, 1024);
  833.         
  834.             InitCursor();
  835.             CenterWindow(dlg);
  836.             ShowWindow(dlg);
  837.             SetPort(dlg);
  838.             FrameDlgRect(dlg, ok);
  839.             ModalDialog((ModalFilterUPP)0, &item);
  840.             switch (item) {
  841.             case ok:
  842.                 str = str_2mortal(Str_new(22,257));
  843.                 str->str_cur = 256;
  844.                     str->str_pok = 1;
  845.                 GetDlgText(dlg, 4, str->str_ptr);
  846.                 str->str_cur = strlen(str->str_ptr);
  847.                 break;
  848.             case cancel:
  849.                 break;
  850.             }
  851.             DisposDialog(dlg);
  852.             
  853.             st[0] = (item == ok)  ? str : &str_undef;
  854.             
  855.             return sp;
  856.         }
  857.     case MP_answer:
  858.         {
  859.             char *        prompt;
  860.             short            item;
  861.             DialogPtr    dlg;
  862.             Str255        tmpPStr;
  863.         
  864.             if (items < 1 || items > 4)
  865.                 fatal("Usage: &MacPerl'Answer(PROMPT [, BUTTON1 [, BUTTON2 [, BUTTON3]]])");
  866.                 
  867.             prompt = (char*)str_get(st[1]);
  868.         
  869.             dlg = GetNewDialog((items>1) ? 1999+items : 2001, NULL, (WindowPtr)-1);
  870.             InitCursor();
  871.             SetDlgText(dlg, 5, prompt);
  872.             
  873.             if (items>1) 
  874.                 for (item = 1; item<items; ++item) {
  875.                     prompt = (char*)str_get(st[item+1]);
  876.                     memcpy(tmpPStr+1, prompt, *tmpPStr = st[item+1]->str_cur);
  877.                     SetCTitle(GetDlgCtrl(dlg, item), tmpPStr);
  878.                 }
  879.             else
  880.                 SetCTitle(GetDlgCtrl(dlg, 1), (StringPtr) "\pOK");
  881.             
  882.             CenterWindow(dlg);
  883.             ShowWindow(dlg);
  884.             SetPort(dlg);
  885.             FrameDlgRect(dlg, ok);
  886.             ModalDialog((ModalFilterUPP)0, &item);
  887.             DisposDialog(dlg);
  888.             
  889.             str_numset(st[0], (items>1) ? (double)(items-item-1) : 0.0);
  890.             
  891.             return sp;
  892.         }
  893.     case MP_choose:
  894.         {
  895.             int domain, type, flags;
  896.             char * prompt;
  897.             char * constraint;
  898.             char * def_addr;
  899.             STR * str;
  900.             
  901.             if (items < 3 || items > 6)
  902.                 fatal("Usage: &MacPerl'Choose(DOMAIN, TYPE, PROMPT [, CONSTRAINT [, FLAGS [, DEFAULT]]])");
  903.                         
  904.             domain = (int)str_gnum(st[1]);
  905.             type = (int)str_gnum(st[2]);
  906.             prompt = (char*)str_get(st[3]);
  907.             constraint = (items>=4) ? (char*)str_get(st[4]) : nil;
  908.             constraint = constraint && st[4]->str_cur ? constraint : nil;
  909.             flags = (items>=5) ? (int)str_gnum(st[5]) : 0;
  910.             def_addr = (items==6) ? (char*)str_get(st[6]) : nil;
  911.             def_addr = def_addr && st[6]->str_cur ? def_addr : nil;
  912.             
  913.             str = str_2mortal(Str_new(22,257));
  914.             str->str_cur = 256;
  915.             str->str_pok = 1;
  916.             
  917.             if (def_addr) {
  918.                 memcpy(str->str_ptr, def_addr, st[6]->str_cur);
  919.                 str->str_ptr[st[6]->str_cur] = 0;    /* Some types require this */
  920.             }
  921.             
  922.             if (choose(domain, type, prompt, constraint, flags, str->str_ptr, (int*)&str->str_cur) < 0)
  923.                 st[0] = &str_undef;
  924.             else
  925.                 st[0] = str_2mortal(str);
  926.                 
  927.                 return sp;
  928.         }
  929.     case MP_pick:
  930.         {    
  931.             char *        prompt;
  932.             short            itemHit;
  933.             Boolean        done;
  934.             DialogPtr    dlg;
  935.             ListHandle    mylist;
  936.             Cell            mycell;
  937.             short            mytype;
  938.             Handle        myhandle;
  939.             Point            cellsize;
  940.             Rect            listrect, dbounds;
  941.             char    *        item;
  942.         
  943.             if (items < 2)
  944.                 fatal("Usage: &MacPerl'Pick(PROMPT, ITEM...)");
  945.                 
  946.             prompt = (char*)str_get(st[1]);
  947.             InitCursor();
  948.             dlg = GetNewDialog(2020, NULL, (WindowPtr)-1);
  949.             
  950.             SetDlgText(dlg, 3, prompt);
  951.             GetDItem(dlg, 4, &mytype, &myhandle, &listrect);
  952.             SetDItem(dlg, 4, mytype, (Handle)&uMacListUpdate, &listrect);
  953.             
  954.             SetPort(dlg);
  955.             InsetRect(&listrect, 1, 1);
  956.             SetRect(&dbounds, 0, 0, 1, items-1);
  957.             cellsize.h = (listrect.right - listrect.left);
  958.             cellsize.v = 17;
  959.         
  960.             listrect.right -= 15;
  961.         
  962.             picklist = LNew(&listrect, &dbounds, cellsize, 0,
  963.                                     dlg, true, false, false, true);
  964.         
  965.             mylist = picklist;
  966.             LDoDraw(false, mylist);
  967.             
  968.             SetCell(mycell, 0, 0);
  969.             for (; mycell.v<items-1; ++mycell.v)    {
  970.                 item = str_get(st[mycell.v+2]);
  971.                 LSetCell(item, st[mycell.v+2]->str_cur, mycell, mylist);
  972.             }
  973.         
  974.             LDoDraw(true, mylist);
  975.             CenterWindow(dlg);
  976.             ShowWindow(dlg);
  977.             
  978.             for (done=false; !done; ) {
  979.                 SetPort(dlg);
  980.                 FrameDlgRect(dlg, ok);
  981.                 ModalDialog((ModalFilterUPP) &uMacListFilter, &itemHit);
  982.                 switch (itemHit) {
  983.                 case ok:
  984.                     SetCell(mycell, 0, 0);
  985.                     done = true;
  986.                     if (!LGetSelect(true, &mycell, picklist))
  987.                         itemHit = cancel;
  988.                     break;
  989.                 case cancel:
  990.                     done = true;
  991.                     break;
  992.                 }
  993.             }    /* Modal Loop */
  994.         
  995.             SetPort(dlg);
  996.             
  997.             LDispose(mylist);
  998.             picklist = NULL;
  999.             DisposDialog(dlg);
  1000.             
  1001.             if (itemHit == ok)
  1002.                 st[0] = str_2mortal(str_smake(st[mycell.v+2]));
  1003.             else
  1004.                 st[0] = &str_undef;    
  1005.  
  1006.             return sp;
  1007.         }
  1008.     case MP_quit:
  1009.         {
  1010.             if (items != 1)
  1011.                 fatal("Usage: &MacPerl'Quit(CONDITION)");
  1012.  
  1013.             gPerlQuit = (int)str_gnum(st[1]);
  1014.  
  1015.              str_numset(st[0], (double) 0.0);
  1016.  
  1017.             return sp;
  1018.         }
  1019.      case MP_faccess:
  1020.          {
  1021.              char *                 file =    str_get(st[1]);
  1022.              unsigned             cmd  =  (unsigned) str_gnum(st[2]);
  1023.              unsigned                uarg;
  1024.             Rect                    rarg;
  1025.             SelectionRecord    sarg;
  1026.             
  1027.              switch (cmd) {
  1028.             case F_GFONTINFO:
  1029.                 if (items > 2)
  1030.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_GFONTINFO)");
  1031.                 if (faccess(file, cmd, (long *)&uarg) < 0) {
  1032.                      st[0] = &str_undef;
  1033.  
  1034.                     return sp;
  1035.                 } else if (!curcsv || curcsv->wantarray != G_ARRAY) {
  1036.                     str_numset(st[0], (double)(uarg >> 16));
  1037.                     
  1038.                     return sp;
  1039.                 } else {
  1040.                     st[0] = str_2mortal(Str_new(22,257));
  1041.                     getfontname(uarg >> 16, st[0]->str_ptr);
  1042.                     st[0]->str_cur = strlen(st[0]->str_ptr);
  1043.                     st[0]->str_pok = 1;
  1044.                     str_numset(st[1], (double)(uarg & 0x0FFFF));
  1045.                     
  1046.                     return sp + 1;
  1047.                 }
  1048.             case F_GSELINFO:
  1049.                 if (items > 2)
  1050.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_GSELINFO)");
  1051.                 if (faccess(file, cmd, (long *)&sarg) < 0) {
  1052.                      st[0] = &str_undef;
  1053.  
  1054.                     return sp;
  1055.                 } else if (!curcsv || curcsv->wantarray != G_ARRAY) {
  1056.                     str_numset(st[0], (double)sarg.startingPos);
  1057.                     
  1058.                     return sp;
  1059.                 } else {
  1060.                     str_numset(st[0], (double) sarg.startingPos);
  1061.                     str_numset(st[1], (double) sarg.endingPos);
  1062.                     str_numset(st[2], (double) sarg.displayTop);
  1063.                     
  1064.                     return sp + 2;
  1065.                 }
  1066.             case F_GTABINFO:
  1067.                 if (items > 2)
  1068.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_GTABINFO)");
  1069.                 if (faccess(file, cmd, (long *)&uarg) < 0) {
  1070.                      st[0] = &str_undef;
  1071.  
  1072.                     return sp;
  1073.                 } else {
  1074.                     str_numset(st[0], (double)uarg);
  1075.                     
  1076.                     return sp;
  1077.                 }
  1078.             case F_GWININFO:
  1079.                 if (items > 2)
  1080.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_GWININFO)");
  1081.                 if (faccess(file, cmd, (long *)&rarg) < 0) {
  1082.                      st[0] = &str_undef;
  1083.  
  1084.                     return sp;
  1085.                 } else if (!curcsv || curcsv->wantarray != G_ARRAY) {
  1086.                     str_numset(st[0], (double)rarg.top);
  1087.                     
  1088.                     return sp;
  1089.                 } else {
  1090.                     astore(stack, sp + 3, Nullstr);        /* extend stack */
  1091.                     st = stack->ary_array + sp;            /* possibly realloced */
  1092.                     str_numset(st[0], (double) rarg.left);
  1093.                     str_numset(st[1], (double) rarg.top);
  1094.                     str_numset(st[2], (double) rarg.right);
  1095.                     st[3] = str_2mortal(str_nmake((double) rarg.bottom));
  1096.                     
  1097.                     return sp + 3;
  1098.                 }
  1099.             case F_SFONTINFO:
  1100.                 if (items < 3 || items > 4)
  1101.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_SFONTINFO, FONT [, SIZE])");
  1102.                 
  1103.                 if (items == 3) {
  1104.                     if (faccess(file, F_GFONTINFO, (long *)&uarg) < 0)
  1105.                         uarg = 9;
  1106.                 } else
  1107.                     uarg = (unsigned) str_gnum(st[4]);
  1108.                 
  1109.                 if (isalpha(*str_get(st[3]))) {
  1110.                     short    family;
  1111.                     
  1112.                     getfnum(str_get(st[3]), &family);
  1113.                     
  1114.                     uarg = (uarg & 0xFFFF) | ((unsigned) family) << 16;
  1115.                 } else 
  1116.                     uarg = (uarg & 0xFFFF) | ((unsigned) str_gnum(st[3])) << 16;
  1117.                 
  1118.                 if (faccess(file, cmd, (long *)uarg) < 0) {
  1119.                      st[0] = &str_undef;
  1120.  
  1121.                     return sp;
  1122.                 } else {
  1123.                     str_numset(st[0], (double) 1.0);
  1124.                     
  1125.                     return sp;
  1126.                 }
  1127.             case F_SSELINFO:
  1128.                 if (items < 4 || items > 5)
  1129.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_SSELINFO, START, END [, TOP])");
  1130.                 
  1131.                 if (items == 4) {
  1132.                     if (faccess(file, F_GSELINFO, (long *) &sarg) < 0) 
  1133.                         sarg.displayTop = (long) str_gnum(st[3]);
  1134.                 } else 
  1135.                     sarg.displayTop = (long) str_gnum(st[5]);
  1136.                     
  1137.                 sarg.startingPos = (long) str_gnum(st[3]);
  1138.                 sarg.endingPos = (long) str_gnum(st[4]);
  1139.                 
  1140.                 if (faccess(file, cmd, (long *)&sarg) < 0) {
  1141.                      st[0] = &str_undef;
  1142.  
  1143.                     return sp;
  1144.                 } else {
  1145.                     str_numset(st[0], (double) 1.0);
  1146.                     
  1147.                     return sp;
  1148.                 }
  1149.             case F_STABINFO:
  1150.                 if (items != 3)
  1151.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_STABINFO, TAB)");
  1152.                 
  1153.                 uarg = (unsigned) str_gnum(st[3]);
  1154.                 
  1155.                 if (faccess(file, cmd, (long *)uarg) < 0) {
  1156.                      st[0] = &str_undef;
  1157.  
  1158.                     return sp;
  1159.                 } else {
  1160.                     str_numset(st[0], (double) 1.0);
  1161.                     
  1162.                     return sp;
  1163.                 }
  1164.             case F_SWININFO:
  1165.                 if (items != 4 && items != 6)
  1166.                     fatal("Usage: &MacPerl'FAccess(FILE, &F_SWININFO, LEFT, TOP [, RIGHT, BOTTOM])");
  1167.                 
  1168.                 if (items == 4) {
  1169.                     if (faccess(file, F_GWININFO, (long *)&rarg) < 0)
  1170.                         rarg.bottom = rarg.right = 400;
  1171.                     else {
  1172.                         rarg.right = rarg.right - rarg.left + (short) str_gnum(st[3]);
  1173.                         rarg.bottom = rarg.bottom - rarg.top + (short) str_gnum(st[4]);
  1174.                     }
  1175.                 } else {
  1176.                     rarg.right = (short) str_gnum(st[5]);
  1177.                     rarg.bottom = (short) str_gnum(st[6]);
  1178.                 }
  1179.                     
  1180.                 rarg.left = (short) str_gnum(st[3]);
  1181.                 rarg.top = (short) str_gnum(st[4]);
  1182.                 
  1183.                 if (faccess(file, cmd, (long *)&rarg) < 0) {
  1184.                      st[0] = &str_undef;
  1185.  
  1186.                     return sp;
  1187.                 } else {
  1188.                     str_numset(st[0], (double) 1.0);
  1189.                     
  1190.                     return sp;
  1191.                 }
  1192.             default:
  1193.                 fatal("&MacPerl'FAccess() can't handle this command");
  1194.             }
  1195.         }
  1196.     case MP_makefsspec:
  1197.         {
  1198.             FSSpec    spec;
  1199.             
  1200.              if (items != 1)
  1201.                 fatal("Usage: &MacPerl'MakeFSSpec(PATH)");
  1202.  
  1203.             if (Path2FSSpec(str_get(st[1]), &spec)) {
  1204.                  st[0] = &str_undef;
  1205.  
  1206.                 return sp;
  1207.             }    
  1208.  
  1209.             str_set(st[0], FSp2Encoding(&spec));
  1210.             return sp;
  1211.         }
  1212.     case MP_makepath:
  1213.         {
  1214.             FSSpec    spec;
  1215.             
  1216.              if (items != 1)
  1217.                 fatal("Usage: &MacPerl'MakePath(FSSPEC)");
  1218.  
  1219.             if (Path2FSSpec(str_get(st[1]), &spec)) {
  1220.                  st[0] = &str_undef;
  1221.  
  1222.                 return sp;
  1223.             }    
  1224.  
  1225.             str_set(st[0], FSp2FullPath(&spec));
  1226.             return sp;
  1227.         }
  1228.     case MP_volumes:
  1229.         {
  1230.             FSSpec spec;
  1231.             
  1232.             if (items != 0)
  1233.                 fatal("Usage: &MacPerl'Volumes()");
  1234.             
  1235.             if (!curcsv || curcsv->wantarray != G_ARRAY) {
  1236.                 Special2FSSpec('macs', kOnSystemDisk, 0, &spec);
  1237.                 GetVolInfo(spec.vRefNum, false, &spec);
  1238.                 
  1239.                 str_set(st[0], FSp2Encoding(&spec));
  1240.                 return sp;
  1241.             } else {
  1242.                 short    index;
  1243.                 
  1244.                 for (index = 0; !GetVolInfo(index+1, true, &spec); ++index)
  1245.                     st[index] = str_2mortal(str_make(FSp2Encoding(&spec), 0));
  1246.                     
  1247.                 return sp + index - 1;
  1248.             }
  1249.         }
  1250.     default:
  1251.          fatal("macperl: Unknown index (Can't happen)");
  1252.        return sp;
  1253.     }
  1254. }
  1255.  
  1256. ComponentInstance gScriptingComponent;
  1257.  
  1258. void ShutDownAppleScript(void)
  1259. {
  1260.     CloseComponent(gScriptingComponent);
  1261.     
  1262.     gScriptingComponent = nil;
  1263. }
  1264.  
  1265. OSErr InitAppleScript(void)
  1266. {
  1267.     OSErr                myErr;
  1268.     ComponentDescription descr;
  1269.     ComponentDescription capabilities;
  1270.     Component            myComponent;
  1271.     EventRecord          myEvent;
  1272.     short                retryCount;
  1273.             
  1274.     retryCount = 0;
  1275.     
  1276.     if (!hasAppleEvents || !hasComponents)
  1277.         return -1;
  1278.         
  1279.     descr.componentType         = kOSAComponentType;
  1280.     descr.componentSubType      = kAppleScriptSubtype;
  1281.     descr.componentManufacturer = (OSType) 0;
  1282.     descr.componentFlags        = kOSASupportsCompiling + 
  1283.                                             kOSASupportsGetSource + 
  1284.                                             kOSASupportsAESending;
  1285.     descr.componentFlagsMask    = descr.componentFlags;
  1286.     
  1287.     myComponent = FindNextComponent(nil, &descr);
  1288.     
  1289.     if (myComponent==nil)
  1290.           return -1;
  1291.     else {
  1292.         myErr = GetComponentInfo(myComponent, &capabilities, nil, nil, nil);
  1293.         gScriptingComponent = OpenComponent(myComponent);
  1294.         if (!gScriptingComponent)
  1295.             return(-1);
  1296.         else
  1297.             atexit(ShutDownAppleScript);
  1298.     }
  1299.         
  1300.     return myErr;
  1301. }
  1302.  
  1303. static int
  1304. doapscript(ix, sp, items)
  1305. int ix;
  1306. register int sp;
  1307. register int items;
  1308. {
  1309.     STR **st = stack->ary_array + sp;
  1310.     register int i;
  1311.     register STR *Str;        /* used in str_get and str_gnum macros */
  1312.      
  1313.      switch (ix) {
  1314.      case MP_reply:
  1315.        {
  1316.             char *    reply;
  1317.  
  1318.             if (items > 1)
  1319.                 fatal("MacPerl'Reply called with more than 1 argument");
  1320.                 
  1321.             reply = (char*)str_get(st[1]);
  1322.             
  1323.             if (gPerlReply)
  1324.                 DisposeHandle(gPerlReply);
  1325.                 
  1326.             PtrToHand(reply, &gPerlReply, strlen(reply));
  1327.  
  1328.              st[0] = &str_undef;
  1329.             
  1330.             return sp;
  1331.         }
  1332.      case MP_doapplescript:
  1333.        {
  1334.             AEDesc    source;
  1335.             AEDesc    result;
  1336.             char *    script;
  1337.             
  1338.             if (items > 1)
  1339.                 fatal("MacPerl'DoAppleScript called with more than 1 argument");
  1340.             
  1341.             if (!gScriptingComponent && InitAppleScript())
  1342.                 fatal("MacPerl'DoAppleScript couldn't initialize AppleScript");
  1343.                 
  1344.             script = (char*)str_get(st[1]);
  1345.             AECreateDesc(typeChar, script, strlen(script), &source);
  1346.             
  1347.             if (!OSADoScript(
  1348.                     gScriptingComponent, 
  1349.                     &source, 
  1350.                     kOSANullScript, 
  1351.                     typeChar, 
  1352.                     kOSAModeCanInteract,
  1353.                     &result))
  1354.             {
  1355.                 AEDisposeDesc(&source);
  1356.                 
  1357.                 if (!AECoerceDesc(&result, typeChar, &source)) {
  1358.                     HLock(source.dataHandle);
  1359.                 
  1360.                     st[0] = str_2mortal(str_make(*source.dataHandle,GetHandleSize(source.dataHandle)));
  1361.                     
  1362.                     AEDisposeDesc(&source);
  1363.                 } else
  1364.                     st[0] = &str_undef;
  1365.             
  1366.                 AEDisposeDesc(&result);
  1367.             } else {
  1368.                 AEDisposeDesc(&source);
  1369.                 
  1370.                 st[0] = &str_undef;
  1371.             }
  1372.             
  1373.             return sp;
  1374.         }
  1375.      default:
  1376.          fatal("doapscript: Unknown index (Can't happen)");
  1377.        return sp;
  1378.      }
  1379. }
  1380.  
  1381. extern int StandAlone;
  1382.  
  1383. static int
  1384. macperlval(ix, str)
  1385. int ix;
  1386. STR *str;
  1387. {
  1388.     VersRecHndl    vers;
  1389.  
  1390.     switch (ix) {
  1391.     case MV_version:
  1392.         vers = (VersRecHndl) GetResource('vers', 1);
  1393.         HLock((Handle) vers);
  1394.         str_nset(str, (char *)(*vers)->shortVersion+1, *(*vers)->shortVersion);
  1395.         if (StandAlone) 
  1396.             str_cat(str, " Application");
  1397.         else
  1398.             str_cat(str, " MPW");
  1399.     }
  1400.     
  1401.     return 0;
  1402. }
  1403.  
  1404. static int
  1405. macperlset(ix, str)
  1406. int ix;
  1407. STR *str;
  1408. {
  1409.     return 0;
  1410. }
  1411.  
  1412. #define STACK_INTERVENTION_LIMIT    8192
  1413.  
  1414. void StackAttack()
  1415. {
  1416.     if (StackSpace() < STACK_INTERVENTION_LIMIT)
  1417.         fatal("Stack space getting low ! Aborting script for your own good...\n");
  1418. }
  1419.